using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using SharedKernel.Infrastructure.Redis;
using StackExchange.Redis;
using System;
using System.Collections.Concurrent;
using System.Text.Json;
using System.Threading.Tasks;

namespace SharedKernel.Infrastructure.Caches
{
    /// <summary>
    /// Redis缓存服务实现
    /// </summary>
    public class RedisCacheService : ICacheService
    {
        private IDatabase _database;
        private readonly RedisOptions _options;
        private readonly ConnectionMultiplexer _connectionMultiplexer;
        private readonly IServiceCollection _services;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="options">Redis配置选项</param>
        public RedisCacheService(IOptions<RedisOptions> options, IServiceCollection services)
        {
            _options = options.Value;
            _services = services;
            try
            {
                _connectionMultiplexer = ConnectionMultiplexer.Connect(_options.ConnectionString,
                    config =>
                    {
                        config.ConnectTimeout = _options.ConnectTimeout;
                        //config.SyncTimeout = _options.SyncTimeout;
                        config.Ssl = _options.Ssl;
                        config.Password = _options.Password;
                    });

                _database = _connectionMultiplexer.GetDatabase(_options.DefaultDatabase);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Redis缓存初始化失败：");
                Console.WriteLine(ex.Message);
            }
        }

        /// <summary>
        /// 是否正常打开
        /// </summary>
        /// <returns></returns>
        public bool IsOpen()
        {
            return _database != null;
        }

        /// <summary>
        /// 变更到另外一个数据库 
        /// </summary>
        /// <param name="db"></param>
        /// <returns></returns>
        public void ChangeDataBase(int db)
        {
            _database = _connectionMultiplexer.GetDatabase(db);
        }

        /// <summary>
        /// 获取缓存项
        /// </summary>
        public async Task<T?> GetAsync<T>(string key)
        {
            var value = await _database.StringGetAsync(key);
            if (value.IsNullOrEmpty)
            {
                return default;
            }

            return JsonSerializer.Deserialize<T>(value!);
        }

        /// <summary>
        /// 设置缓存项
        /// </summary>
        public async Task<bool> SetAsync<T>(string key, T value, TimeSpan? expiration = null)
        {
            var jsonValue = JsonSerializer.Serialize(value);
            return await _database.StringSetAsync(
                key,
                jsonValue,
                expiration ?? TimeSpan.FromMinutes(30));
        }

        /// <summary>
        /// 删除缓存项
        /// </summary>
        public async Task<bool> RemoveAsync(string key)
        {
            return await _database.KeyDeleteAsync(key);
        }

        /// <summary>
        /// 检查缓存项是否存在
        /// </summary>
        public async Task<bool> ExistsAsync(string key)
        {
            return await _database.KeyExistsAsync(key);
        }

        /// <summary>
        /// 获取缓存项
        /// </summary>
        public T? Get<T>(string key)
        {
            var value = _database.StringGet(key);
            if (value.IsNullOrEmpty)
            {
                return default;
            }

            return JsonSerializer.Deserialize<T>(value!);
        }

        /// <summary>
        /// 设置缓存项
        /// </summary>
        public bool Set<T>(string key, T value, TimeSpan? expiration = null)
        {
            var jsonValue = JsonSerializer.Serialize(value);
            return _database.StringSet(
                key,
                jsonValue,
                expiration ?? TimeSpan.FromMinutes(30));
        }

        /// <summary>
        /// 删除缓存项
        /// </summary>
        public bool Remove(string key)
        {
            return _database.KeyDelete(key);
        }

        /// <summary>
        /// 检查缓存项是否存在
        /// </summary>
        public bool Exists(string key)
        {
            return _database.KeyExists(key);
        }

    }
}